import config, {
  constants
} from './../config';
import {
  formatData,
  checkState,
  checkSign
} from './interface';
import {
  responseResult,
  domainName,
  empty
} from './helper'
/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [options] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default function request(url, options, loading = true) {

  // 设置请求的 header，header 中不能设置 Referer。
  const header = config.service.headers;

  //（需大写）有效值：OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
  const method = config.service.method;

  // 如果设为json，会尝试对返回的数据做一次 JSON.parse
  const dataType = config.service.default_return_type;

  // 预发送给服务器的数据
  const data = formatData(options);

  //发起网络请求
  let promise = new Promise(function(resolve, reject) {
    if (loading) {
      wx.showLoading({
        title: '加载中',
        mask: true
      });
    }
    wx.request({
      // 开发者服务器接口地址
      url: url,

      // 请求的参数
      data: data,

      header: header,

      // 请求方式
      method: method,

      // 服务成功返回数据类型
      dataType: dataType,

      // 收到开发者服务成功返回的回调函数
      success(result) {
        // 异步操作成功
        resolve(result);
      },

      // 接口调用失败的回调函数
      fail(err) {
        console.error('登录失败，可能是网络错误或者服务器发生异常')
        // 异步操作失败
        reject(err);
      },
      // 接口调用结束的回调函数（调用成功、失败都会执行）
      complete(result) {
        if (loading) {
          wx.hideLoading();
        }
      }
    });
  });

  return promise.
  then(checkStatus).
  then(checkReferer).
  then(checkCode).
  then(checkCSRF).
  then(checkTime).
  then(checkSignature).
  catch(function(error) {
    // 函数运行时发生的错误
    console.warn('Promise catch', error);
  });
}

// Referer
function checkReferer(response) {
  const Referer = response.header.Referer;
  const host = domainName(Referer);
  if (host === config.service.referer) {
    return response.data;
  }
  const msg = 'Referer效验失败'
  message(msg);
  const error = new Error(msg);
  error.response = response;
  throw error;
}

// 返回码异常校验
function checkCode(data) {
  if (data.code === 1) {
    return data;
  }
  responseResult(data);
  const error = new Error(data.msg);
  error.response = data;
  throw error;
}

// 签名验证
function checkSignature(data) {
  if (checkSign(data)) {
    return data.data;
  }
  const msg = '数据签名错误';
  message(msg);
  const error = new Error(msg);
  error.response = data;
  throw error
}

// 超时验证
function checkTime(data) {
  // API网络请求是否超时
  if (config.service.times_out > 0) {
    if (!empty(data.timestamps) && ((new Date().getTime() / 1000) - data.timestamps) <= config.service.times_out) {
      return data;
    }
    const msg = '网络请求已超时';
    message(msg);
    const error = new Error(msg);
    error.response = data;
    throw error;
  } else {
    return data;
  }
}

// state防止CSRF
function checkCSRF(data) {
  if (checkState(data)) {
    return data;
  }
  const msg = 'State验证失败';
  message(msg);
  const error = new Error(msg);
  error.response = data;
  throw error;
}

// 检测通信状态
function checkStatus(response) {
  if (response.statusCode >= 200 && response.statusCode < 300) {
    return response;
  }
  const msg = '与服务器通信失败，可能是网络错误或者服务器发生异常';
  message(msg);
  const error = new Error(msg);
  error.response = response;
  throw error;
}

// 消息提示
function message(msg) {
  wx.showModal({
    content: msg,
    showCancel: false,
  })
}